﻿using Abp;
using Abp.Application.Services;
using Abp.AspNetCore.Mvc;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Domain.Entities;
using Abp.Domain.Repositories;
using Abp.EntityFrameworkCore.Repositories;
using Abp.Events.Bus;
using Abp.Extensions;
using Abp.Runtime.Session;
using Abp.Runtime.Validation;
using Abp.UI;
using ALEXFW.Authorization;
using ALEXFW.Authorization.Users;
using ALEXFW.BasicModel;
using ALEXFW.StudentGeneralInfo.Dto;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Net;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ALEXFW.StudentGeneralInfo
{
    [AbpAuthorize(PermissionNames.Pager_User)]
    public class StudentGeneralInfoAppService : ALEXFWAppServiceBase, IStudentGeneralInfoAppService
    {
        private IRepository<Student, Guid> _studentContext;
        private IRepository<Exercise, Guid> _exerciseContext;
        private IRepository<Group, Guid> _groupContext;
        private IRepository<Classes, Guid> _classContext;
        private IRepository<College, Guid> _collegeContext;
        private IRepository<Category, Guid> _categoryContext;
        private IRepository<School, Guid> _schoolContext;
        private IRepository<Teacher, Guid> _teacherContext;
        private IRepository<ApplyRecord, Guid> _applyRecordContext;
        private IRepository<TopicRepository, Guid> _topicContext;
        private IAbpSession _session;

        public StudentGeneralInfoAppService(
            IAbpSession session,
            IRepository<Student, Guid> studentContext,
            IRepository<Exercise, Guid> exerciseContext,
            IRepository<Group, Guid> groupContext,
            IRepository<Classes, Guid> classContext,
            IRepository<College, Guid> collegeContext,
            IRepository<School, Guid> schoolContext,
            IRepository<Category, Guid> categoryContext,
            IRepository<Teacher, Guid> teacherContext,
            IRepository<ApplyRecord, Guid> applyRecordContext,
            IRepository<TopicRepository, Guid> topicContext
            )
        {
            _studentContext = studentContext;
            _exerciseContext = exerciseContext;
            _groupContext = groupContext;
            _classContext = classContext;
            _collegeContext = collegeContext;
            _categoryContext = categoryContext;
            _schoolContext = schoolContext;
            _teacherContext = teacherContext;
            _applyRecordContext = applyRecordContext;
            _topicContext = topicContext;
            _session = session;
        }

        /// <summary>
        /// 获取学生信息
        /// </summary>
        /// <returns></returns>
        public async Task<StudentInfoDto> GetStudentInfo()
        {
            var userID = _session.UserId;
            if (userID != null)
            {
                var student = await _studentContext.SingleAsync(x => x.UserID == userID);
                var group = await _groupContext.FirstOrDefaultAsync(x => x.Id == student.GroupID);

                var result = new StudentInfoDto
                {
                    StudentID = student.StudentID,
                    Name = student.Name,
                    Sex = student.Sex,
                    PhoneNumber = student.PhoneNumber,
                    StartInternshipTime = student.StartInternshipTime.ToString("yyyy-MM-dd"),
                    PracticeTotalScore = student.PracticeTotalScore,
                    GroupName = group?.Name,
                    ClassName = (await _classContext.SingleAsync(x => x.Id == student.ClassesID)).Name,
                    CollegeName = (await _collegeContext.SingleAsync(x => x.Id == student.CollegeID)).Name
                };
                return result;
            }
            else
                throw new AbpAuthorizationException();
        }

        /// <summary>
        /// 更改学生信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<bool> UpdateStudentInfo(StudentInfoDto input)
        {
            if (input == null) throw new AbpCustomStatusCodeException(204, "请填写要更改的信息");
            var userID = _session.UserId;
            if (userID != null)
            {
                var student = await _studentContext.SingleAsync(x => x.UserID == userID);
                student.PhoneNumber = input.PhoneNumber;
                var result = await _studentContext.UpdateAsync(student);
                return result != null ? true : false;
            }
            else
                throw new AbpAuthorizationException();
        }

        /// <summary>
        /// 获取测试
        /// </summary>
        /// <returns></returns>
        public async Task<List<ExercisesDto>> GetExercise()
        {
            var userID = _session.UserId;
            if (userID != null)
            {
                var groupID = (await _studentContext.SingleAsync(x => x.UserID == userID)).GroupID;
                if (groupID == null) throw new AbpCustomStatusCodeException(204, "未找到该小组，请重试");

                var exerciseList = await _exerciseContext.GetAllListAsync(x => x.GroupID == groupID && x.PublishStatus == true);

                return ObjectMapper.Map<List<ExercisesDto>>(exerciseList);
            }
            else
                throw new AbpAuthorizationException();
        }

        /// <summary>
        /// 获取类别
        /// </summary>
        /// <returns></returns>
        public async Task<List<CategoryDto>> GetCategory()
        {
            var userID = _session.UserId;
            if (userID != null)
            {
                var category = await _categoryContext.GetAllListAsync();
                return ObjectMapper.Map<List<CategoryDto>>(category);
            }
            else
                throw new AbpAuthorizationException();
        }

        /// <summary>
        /// 通过类别ID获取实习小组
        /// </summary>
        /// <param name="id">类别ID</param>
        /// <returns></returns>
        public async Task<List<GroupDto>> GetGroupByCategoryID(string id)
        {
            if (string.IsNullOrEmpty(id)) throw new AbpCustomStatusCodeException(204, "请选择正确的类别");
            var categroyID = Guid.Parse(id);
            var userID = _session.UserId;
            if (userID != null)
            {
                var groupList = new List<GroupDto>();
                var groups = await _groupContext.GetAllListAsync(x => x.CategoryID == categroyID);
                foreach (var item in groups)
                {
                    var teacher = _teacherContext.Single(x => x.Id == item.TeacherID);
                    groupList.Add(new GroupDto
                    {
                        Id = item.Id,
                        Name = item.Name,
                        Quota = item.Quota,
                        TeacherName = teacher.Name,
                        TeacherPhone = teacher.PhoneNumber
                    });
                }
                return groupList;
            }
            else
                throw new AbpAuthorizationException();
        }

        /// <summary>
        /// 获取学生的实习小组
        /// </summary>
        /// <returns></returns>
        public async Task<GroupDto> GetGroup()
        {
            var userID = _session.UserId;
            if (userID != null)
            {
                var student = await _studentContext.SingleAsync(x => x.UserID == userID);
                if (student.GroupID == Guid.Empty) throw new AbpCustomStatusCodeException(204, "您未加入实习小组，请到申请页面进行申请");
                var group = await _groupContext.SingleAsync(x => x.Id == student.GroupID);
                var teacher = await _teacherContext.SingleAsync(x => x.Id == group.TeacherID);
                return new GroupDto
                {
                    Id = group.Id,
                    Name = group.Name,
                    TeacherName = teacher.Name,
                    TeacherPhone = teacher.PhoneNumber
                };
            }
            else
                throw new AbpAuthorizationException();
        }

        /// <summary>
        /// 申请实习小组
        /// </summary>
        /// <param name="id">小组ID</param>
        /// <returns></returns>
        public async Task<bool> ApplyGroup(GroupInput input)
        {
            if (string.IsNullOrEmpty(input.ID)) throw new AbpCustomStatusCodeException(204, "请选择实习小组");
            var groupID = Guid.Parse(input.ID);
            var userID = _session.UserId;
            if (userID != null)
            {
                var student = await _studentContext.FirstOrDefaultAsync(x => x.UserID == userID);
                var group = await _groupContext.FirstOrDefaultAsync(x => x.Id == groupID);
                if (group == null) throw new AbpCustomStatusCodeException(204, "未找到该实习小组");
                var applyRecord = new ApplyRecord
                {
                    Id = Guid.NewGuid(),
                    StudentID = student.Id,
                    GroupID = groupID,
                    ApplyStatus = ApplyStatus.正在审核,
                    ApplyTime = DateTime.Now
                };
                var record = await _applyRecordContext.FirstOrDefaultAsync(x => x.StudentID == student.Id);
                if (record != null)
                {
                    return false;
                }
                var result = await _applyRecordContext.InsertAndGetIdAsync(applyRecord);
                if (result != null)
                    return true;
                else
                    return false;
            }
            else
                throw new AbpAuthorizationException();
        }

        /// <summary>
        /// 获取学生加入的实习小组和该小组里的发布的测试
        /// </summary>
        /// <returns></returns>
        public async Task<GroupDto> GetUserGroupAndExercise()
        {
            var userID = _session.UserId;
            if (userID != null)
            {
                var student = await _studentContext.SingleAsync(x => x.UserID == userID);
                if (student.GroupID != Guid.Empty && student.GroupID != null)
                {
                    var group = await _groupContext.SingleAsync(x => x.Id == student.GroupID);
                    var exercises = await _exerciseContext.GetAllListAsync(x => x.GroupID == student.GroupID);
                    var exerciseList = ObjectMapper.Map<List<ExercisesDto>>(exercises);

                    var result = new GroupDto
                    {
                        Id = group.Id,
                        Name = group.Name,
                        Exercises = exerciseList
                    };
                    return result;
                }
                else
                    return null;
            }
            else
                throw new AbpAuthorizationException();
        }

        /// <summary>
        /// 通过测试ID查找题目
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<TopicDto>> GetTopicsByExerciseID(string id)
        {
            if (string.IsNullOrEmpty(id)) throw new AbpCustomStatusCodeException(204, "请选择测试");
            var exerciseID = Guid.Parse(id);
            var userID = _session.UserId;
            if (userID != null)
            {
                var topics = await _topicContext.GetAllListAsync(x => x.ExerciseID == exerciseID);
                if (topics != null && topics.Count != 0)
                {
                    return ObjectMapper.Map<List<TopicDto>>(topics);
                }
                else
                    return null;
            }
            else
                throw new AbpAuthorizationException();
        }
    }
}
